package ru.fadeev.crammer.data;

import java.util.Vector;


/**
 * When user edits words list in AddEditSheetDialog WordEditList class is used
 * to keep information about changes to words that is about to made. And then
 * this information is used by Sheet's saveWords function if user accepts all
 * changes he makes. 
 * @author Konstantin Fadeyev
 *
 */
public class WordEditList {
	
	/**
	 * Vector of words with information about what will be done with word 
	 * (inserted, changed, deleted, left intact)
	 */
	private Vector<WordEditListRecord> editList;
	
	
	/** 
	 * The same as editList but without records with DELETED status. Used to
	 * accelerate some operations of getting non-deleted words (words that are
	 * about to delete aren't shown in AddEditSheetDIalog)
	 */
	private Vector<WordEditListRecord> nonDeleteList;   
	
	
	/**
	 * Constructs WordEditList
	 */
	public WordEditList() {
		editList = new Vector<WordEditListRecord>();
		nonDeleteList = new Vector<WordEditListRecord>();
	}
	
	
	/**
	 * Constructs WordEditList and initializes it with words from sheet
	 * @param sheet object of Sheet to initialize WordEditList
	 */
	public WordEditList(Sheet sheet) {
		editList = new Vector<WordEditListRecord>();
		nonDeleteList = new Vector<WordEditListRecord>();
    	for (int i = 0; i < sheet.size(); i++) {
    		WordEditListRecord editListRecord = new WordEditListRecord();
    		editListRecord.status = WordEditListRecord.NO_CHANGE;
    		editListRecord.setIndex(i);
    		editListRecord.setWordRecord(new WordRecord()); 
    		editListRecord.getWordRecord().copy(sheet.getWordRecord(i));
    		editList.addElement(editListRecord);
    		nonDeleteList.addElement(editListRecord);
    	}
	}
	
	
	/**
	 * Adds new record with status INSERTED to the end of WordEditList
	 * @param word word text of new record
	 * @param transcription word transcription of new record
	 * @param translation word translation of new record
	 * @param prompt word prompt of new record
	 */
	public void addRecord(String word, String transcription, 
			String translation, String prompt) {
		WordEditListRecord newEditListRecord = new WordEditListRecord();
		WordRecord newWordRecord = new WordRecord();
		newWordRecord.setWord(word);
		newWordRecord.setTranscription(transcription);
		newWordRecord.setTranslation(translation);
		newWordRecord.setPrompt(prompt);
		newEditListRecord.setWordRecord(newWordRecord);
		newEditListRecord.status = WordEditListRecord.INSERTED;
		editList.addElement(newEditListRecord);
		nonDeleteList.addElement(newEditListRecord);
	}

	
	/**
	 * Deletes records specified by nonDeleteIndices array from the WordEditList
	 * @param nonDeleteIndices array of indices in list (not including records 
	 * with DELETED status) that will be deleted
	 */
	public void deleteRecords(int[] nonDeleteIndices) {
		for(int i = nonDeleteIndices.length - 1; i >= 0; i--) {
			WordEditListRecord record = 
				nonDeleteList.elementAt(nonDeleteIndices[i]);
			if(record.status == WordEditListRecord.INSERTED) {				
				editList.remove(record);
				nonDeleteList.remove(record);
			} else {				
				record.status = WordEditListRecord.DELETED;
				nonDeleteList.remove(record);
			}
    	}
	}
	
	
	/**
	 * Returns record of list (not including records with DELETED status)
	 * specified by nonDeleteIndex.
	 * @param nonDeleteIndex index of record in list (not including records 
	 * with DELETED status)
	 * @return record of list (not including records with DELETED status)
	 * specified by nonDeleteIndex.
	 */
	public WordEditListRecord getNonDeleteRecord(int nonDeleteIndex) {
		return nonDeleteList.elementAt(nonDeleteIndex);
	}
	
	
	/**
	 * Returns record of list specified by index
	 * @param index index of record in list
	 * @return record of list specified by index
	 */
	public WordEditListRecord getRecord(int index) {
		return editList.elementAt(index);
	}
	
	
	/**
	 * Inserts new record with status INSERTED into the WordEditList.
	 * @param word word text of new record
	 * @param transcription word transcription of new record
	 * @param translation word translation of new record
	 * @param prompt word prompt of new record
	 * @param nonDeleteIndex index in list (not including records with DELETED 
	 * status) where new record will be inserted 
	 */
	public void insertRecord(String word, String transcription, 
			String translation, String prompt, 
			int nonDeleteIndex) {
		WordEditListRecord newEditListRecord = new WordEditListRecord();
		WordRecord newWordRecord = new WordRecord();
		newWordRecord.setWord(word);
		newWordRecord.setTranscription(transcription);
		newWordRecord.setTranslation(translation);
		newWordRecord.setPrompt(prompt);
		newEditListRecord.setWordRecord(newWordRecord);
		newEditListRecord.status = WordEditListRecord.INSERTED;
		int index;
		if(nonDeleteIndex < nonDeleteSize()) {
			WordEditListRecord record = nonDeleteList.elementAt(nonDeleteIndex);
			index = editList.indexOf(record);
		} else {
			index = nonDeleteSize();
		}
		editList.insertElementAt(newEditListRecord, index);
		nonDeleteList.insertElementAt(newEditListRecord, nonDeleteIndex);
	}
	
	
	/**
	 * Returns number of records in list not including records with DELETED 
	 * status
	 * @return number of records without DELETED status
	 */
	public int nonDeleteSize() {
		return nonDeleteList.size();
	}
	
	
	/**
	 * Returns number of records in list
	 * @return number of records in list
	 */
	public int size() {
		return editList.size();
	}
	
	
	/**
	 * Swaps to records in the WordEditList
	 * @param nonDeleteIndex1 index of first record in list (not including 
	 * records with DELETED status)
	 * @param nonDeleteIndex2 index of second record in list (not including 
	 * records with DELETED status)
	 */
	public void swapRecords(int nonDeleteIndex1, int nonDeleteIndex2) {
		WordEditListRecord record1 = 
			(WordEditListRecord)nonDeleteList.elementAt(nonDeleteIndex1);
		WordEditListRecord record2 = 
			(WordEditListRecord)nonDeleteList.elementAt(nonDeleteIndex2);	
		int index1 = editList.indexOf(record1);
		int index2 = editList.indexOf(record2);
		editList.setElementAt(record1, index2);
		editList.setElementAt(record2, index1);
		nonDeleteList.setElementAt(record1, nonDeleteIndex2);
		nonDeleteList.setElementAt(record2, nonDeleteIndex1);
	}
}
